package com.dou.cloud.bridge.redis.handler;


import com.dou.cloud.bridge.redis.enums.RedissonEnum;
import com.due.basic.tookit.exception.LogicException;
import com.due.basic.tookit.function.DueVoidProducer;
import com.due.basic.tookit.utils.DateUtil;
import org.redisson.api.RLock;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;

import static com.due.basic.tookit.constant.RedisConstant.AFTER_TRYING;
import static com.due.basic.tookit.constant.RedisConstant.DO_NOT_OPERATE_FREQUENTLY;
import static com.due.basic.tookit.enums.ErrorEnum.LOCK_EXPIRED_RELEASED;

/**
 * @Author daizl
 * @Date 2024 06 19 18 15
 **/
@Component
public class TryLock extends AbstractDistributedLockHandler {


    @Override
    public <T> T tryLock(Supplier<Object> supplier, String key, long waitTime, long leaseTime, TimeUnit timeUnit) {
        isRedissonClient();
        RLock lock = redissonClient.getLock(key);
        // 锁未失效，则直接返回
        if (lock.isLocked()) {
            throw new LogicException(DO_NOT_OPERATE_FREQUENTLY + leaseTime + DateUtil.toChinese(timeUnit) + AFTER_TRYING);
        }
        try {
            // todo tryLock目前存在问题
            boolean isLocked = lock.tryLock(waitTime, leaseTime, timeUnit);
            if (isLocked) {
                supplier.get();
            } else {
                throw new LogicException(DO_NOT_OPERATE_FREQUENTLY + leaseTime + DateUtil.toChinese(timeUnit) + AFTER_TRYING);
            }
        } catch (IllegalMonitorStateException ex) {
            // Lock has expired, handle releasing the lock here
            lock.unlock();
            throw new LogicException(LOCK_EXPIRED_RELEASED);
        } catch (Exception ex) {
            throw new LogicException(ex);
        }
        return (T) lock;
    }

    @Override
    public Integer getType() {
        return RedissonEnum.TRY_LOCK.getType();
    }
}
